package com.bestv.search.management.datasyn;

import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.*;
import com.bestv.search.common.model.uid.UID;
import com.bestv.search.common.util.CharUtil;
import com.bestv.search.common.util.ChineseCharToEn;
import com.bestv.search.common.util.StringConst;

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;

public class CmsDbProgramSyncer extends ProgramSyncerImpl {
    final static String sDBDriver = "oracle.jdbc.driver.OracleDriver";

    final static int typeSeries = 3100;
    final static int progValid = 1;

    String orclUrl = null;
    String encoding = "ISO8859_1";
    String user = null;
    String pass = null;
    String programView = null;
    String siteCode = null;

    public CmsDbProgramSyncer() {
    }

    public CmsDbProgramSyncer(Map<String, String> p) throws Exception {
        this.setProps(p);
        justDoIt();
    }

    public boolean init(Map<String, String> properties) {
        if (!initLastSyncTime(StringConst.BESTV_CMS, 1, StringConst.CMS_PROGRAM_SYNC_TIME)) {
            return false;
        }
        if (props.get("orclUrl") == null || props.get("orclUrl").length() == 0) {
            logger.error("orclUrl is empty!");
            result = false;
            return false;
        }
        if (props.get("program") == null || props.get("program").length() == 0) {
            logger.error("program view is empty!");
            result = false;
            return false;
        }
        if (props.get("encoding") == null || props.get("encoding").length() == 0) {
            logger.warn("encoding is empty, use ISO8859_1");
        } else {
            encoding = props.get("encoding");
        }
        orclUrl = props.get("orclUrl");
        user = props.get("user");
        pass = props.get("pass");
        programView = props.get("program");
        siteCode = props.get("branch").toUpperCase();
        return true;
    }

    public boolean updateProgram() throws Exception {
        logger.info("now read from cms db program and update to search's");
        thisSyncTime = lastSyncSuccessfullTime;

        Connection conn = null;
        ResultSet rs = null;
        Statement stmt = null;

        Type type = new Type();
        type.setId(3L);
        type.setName("VOD");
        type.setDescription("VOD");

        String syncMessage = "Success sync program from CMS system @ " + new Date();
        try {
            Class.forName(sDBDriver);
            conn = DriverManager.getConnection(orclUrl, user, pass);
            stmt = conn.createStatement();

            rs = stmt.executeQuery("select * from " + programView + " where episode_number = 0 and update_time >= "
                    + "to_date('" + timeformat.format(lastSyncSuccessfullTime)
                    + "','YYYY-MM-DD HH24:MI:SS') order by update_time");
            logger.info("A new batch begins at program_update_time " + timeformat.format(lastSyncSuccessfullTime));

            boolean isValid, isNew = false;
            int index = 0;
            while (rs.next()) {
                Program program = new Program();
                program.setHitCount(0);
                Date now = new Date();
                try {
                    isValid = rs.getInt("status") == progValid;
                    Date ut = rs.getTimestamp("update_time");
                    program.setUpdateTime(ut);
                    if (thisSyncTime == null || ut.after(thisSyncTime)) {
                        thisSyncTime = ut;
                    }

                    DataSourceKey dsKey = DataSourceKeyUtil.convert(siteCode);
                    List<Program> pl = pm.getProgramByCode(dsKey, rs.getString("code"));
                    if (pl != null && pl.size() > 0) {
                        isNew = false;
                        for (int x = 0; x < pl.size(); x++) {
                            Program pg = pl.get(x);
                            if (x == 0) {
                                program = pg;
                                program.setUpdateFlag(isValid ? 1 : 2);
                            } else {
                                pg.setUpdateFlag(2);
                                pg.setUpdateTimeForIndex(now);
                                pg.setUpdateTimeMillis(Long.valueOf(updatetimeformat.format(ut)));
                                vm.saveUpdateInfo(dsKey, pg);
                            }
                        }
                    } else {
                        isNew = true;
                        program.setUpdateFlag(isValid ? 0 : 2);
                    }
                    program.setCode(rs.getString("code"));
                    String name = unifyStr(rs.getString("name"));
                    program.setName(name);
                    if (program.getNamePY() == null || "".equals(program.getNamePY())) {
                        String abbreviation = ChineseCharToEn.getAllFirstLetter(name);
                        String splitTokens = splitToken(name);
                        program.setNamePY(abbreviation + " " + CharUtil.charToNum(abbreviation) + " " + splitTokens);
                    }
                    program.setStatus(rs.getInt("status"));

                    String p_type = unifyStr(rs.getString("content_type"));
                    BizType bizType = bm.getBizTypeByName(dsKey, p_type);
                    if (bizType == null) {
                        p_type = "其他";
                        bizType = bm.getBizTypeByName(dsKey, p_type);
                    }
                    program.setP_type(p_type);
                    program.setBizType(bizType);

                    program.setGenre(unifyStr(rs.getString("genre")));
                    String kws = rs.getString("keywords");
                    Set<Keyword> keys = new HashSet<Keyword>();
                    if (kws != null && kws.trim().length() != 0) {
                        String[] keywords = unifyStr(rs.getString("keywords")).split("[\\[\\]\\-,;、 ]+");
                        for (String key : keywords) {
                            if (key == null || "".equals(key))
                                continue;
                            Keyword k = km.getKeywordByName(dsKey, key);
                            if (k == null) {
                                k = new Keyword();
                                k.setKeyword(key);
                            }
                            keys.add(k);
                        }
                    }
                    program.setKeywords(keys);
                    String tgs = rs.getString("tags");
                    Set<Tag> ts = new HashSet<Tag>();
                    if (tgs != null && tgs.trim().length() != 0) {
                        String[] tags = unifyStr(rs.getString("tags")).split("[\\[\\]\\-,;、 ]+");
                        for (String tg : tags) {
                            if (tg == null || "".equals(tg))
                                continue;
                            Tag t = tm.getTagByName(dsKey, tg);
                            if (t == null) {
                                t = new Tag();
                                t.setTag(tg);
                            }
                            ts.add(t);
                        }
                    }
                    program.setTags(ts);
                    program.setType(type);
                    program.setIsSeries(typeSeries == rs.getInt("type"));
                    program.setDescription(unifyStr(rs.getString("description")));
                    String actors = unifyStr(rs.getString("actor_display"));
                    program.setActors(actors);
                    if (program.getActorsPY() == null || "".equals(program.getActorsPY())) {
                        String actorsStr = ChineseCharToEn.getAllFirstLetter(actors);
                        program.setActorsPY(actorsStr + " " + CharUtil.charToNum(actorsStr));
                    }
                    String directors = unifyStr(rs.getString("writer_display"));
                    program.setDirectors(directors);
                    if (program.getDirectorsPY() == null || "".equals(program.getDirectorsPY())) {
                        String directorStr = ChineseCharToEn.getAllFirstLetter(directors);
                        program.setDirectorsPY(directorStr + " " + CharUtil.charToNum(directorStr));
                    }
                    program.setRegion(unifyStr(rs.getString("region")));
                    program.setIssueYear(rs.getInt("issue_year") == 0 ? null : yearformat.parse(String.valueOf(rs
                            .getInt("issue_year"))));
                    program.setUpdateTimeForIndex(now);
                    program.setUpdateTimeMillis(Long.valueOf(updatetimeformat.format(ut)));
                    if (isNew) {
                        program.setId(new Long(UID.getUID(program)));
                    }
                    vm.saveUpdateInfo(dsKey, program);
                } catch (Exception e) {
                    // ignore one record exception, just log it.
                    logger.error("read program error! pcode=" + rs.getString("code"));
                }
                index++;
                if (index % 20000 == 0) {
                    logger.info("This batch of 20000 records ends at program_update_time " + thisSyncTime);
                    break;
                }
            }
            rs.close();
        } catch (Exception e) {
            System.out.println(e);
            syncMessage = "Failed sync program from CMS system @ " + new Date();
            result = false;
            throw e;
        } finally {
            if (rs != null)
                rs.close();
            if (stmt != null)
                stmt.close();
            if (conn != null)
                conn.close();

            // Update Sync status.
            updateSyncStatus(StringConst.BESTV_CMS, 1, StringConst.CMS_PROGRAM_SYNC_TIME, syncMessage, thisSyncTime);
        }

        return true;
    }

    String unifyStr(String s) throws UnsupportedEncodingException {
        if (s == null)
            return null;
        String toCode = encoding.equalsIgnoreCase("iso-8859-1") ? "gbk" : "utf-8";
        return new String(s.getBytes(encoding), toCode).trim();
    }
}
